home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / xpaint-2.1.1 / cutCopyPaste.c < prev    next >
C/C++ Source or Header  |  1995-05-03  |  14KB  |  552 lines

  1. /* +-------------------------------------------------------------------+ */
  2. /* | Copyright 1993, David Koblas (koblas@netcom.com)                  | */
  3. /* |                                                                   | */
  4. /* | Permission to use, copy, modify, and to distribute this software  | */
  5. /* | and its documentation for any purpose is hereby granted without   | */
  6. /* | fee, provided that the above copyright notice appear in all       | */
  7. /* | copies and that both that copyright notice and this permission    | */
  8. /* | notice appear in supporting documentation.  There is no           | */
  9. /* | representations about the suitability of this software for        | */
  10. /* | any purpose.  this software is provided "as is" without express   | */
  11. /* | or implied warranty.                                              | */
  12. /* |                                                                   | */
  13. /* +-------------------------------------------------------------------+ */
  14.  
  15. #include <X11/StringDefs.h>
  16. #include <X11/Intrinsic.h>
  17. #include <X11/Xatom.h>
  18. #include "Paint.h"
  19. #include "xpaint.h"
  20. #include "misc.h"
  21. #include "menu.h"
  22. #include "palette.h"
  23. #include "image.h"
  24.  
  25.  
  26. Image *ImageSmooth(Image *);
  27. Image *ImageSharpen(Image *);
  28. Image *ImageInvert(Image *);
  29. Image *ImageEdge(Image *);
  30. Image *ImageEmbose(Image *);
  31. Image *ImageOilPaint(Image *);
  32.  
  33. extern void     *GraphicGetData(Widget);
  34. static Boolean    selectionOwner = False;
  35.  
  36. /*
  37. **  This really should be a "local" or malloced variable
  38. */
  39. typedef struct {
  40.     Pixmap    pixmap;
  41.     int    count;
  42.     int    width, height, depth;
  43. } selectInfo;
  44.  
  45. static void setToSelectOp()
  46. {
  47.     static String    names[2] = { "selectBox", "selectArea" };
  48.     OperationSet(names, 2);
  49. }
  50.  
  51. static void selectionLost(Widget w, Atom *selection)
  52. {
  53.     selectionOwner = False;
  54. }
  55. static void selectionDone(Widget w, Atom *selection, Atom *target)
  56. {
  57.     /* empty */
  58. }
  59. static Boolean selectionConvert(Widget w, Atom *selection, Atom *target,
  60.             Atom *type, XtPointer *value, unsigned long *len,
  61.             int *format)
  62. {
  63.     Pixmap    src = Global.region.pix;
  64.     Pixmap    *pix, np;
  65.     GC    gc;
  66.     int    wth, hth, dth;
  67.  
  68.     if (src == None)
  69.         return False;
  70.  
  71.     if (*target != XA_PIXMAP && *target != XA_BITMAP)
  72.         return False;
  73.  
  74.     pix = XtNew(Pixmap);
  75.  
  76.     GetPixmapWHD(XtDisplay(w), src, &wth, &hth, &dth);
  77.     np = XCreatePixmap(XtDisplay(w), XtWindow(w), wth, hth, dth);
  78.     gc = XCreateGC(XtDisplay(w), np, 0, 0);
  79.     XCopyArea(XtDisplay(w), src, np, gc, 0, 0, wth, hth, 0, 0);
  80.     XFreeGC(XtDisplay(w), gc);
  81.  
  82.     *pix = np;
  83.  
  84.     *type   = XA_PIXMAP;
  85.     *len    = 1;
  86.     *format = 32;
  87.     *value  = (XtPointer)pix;
  88.  
  89.     return True;
  90. }
  91.  
  92. void StdCopyCallback(Widget w, XtPointer paintArg, String *nm, XEvent *event)
  93. {
  94.     Widget        paint = (Widget)paintArg;
  95.     Pixmap        pix, mask;
  96.     int        width, height;
  97.  
  98.     if (!PwRegionGet(paint, &pix, &mask))
  99.         return;
  100.  
  101.     GetPixmapWHD(XtDisplay(paint), pix, &width, &height, NULL);
  102.  
  103.     if (Global.region.pix != None)
  104.         XFreePixmap(XtDisplay(paint), Global.region.pix);
  105.     if (Global.region.mask != None)
  106.         XFreePixmap(XtDisplay(paint), Global.region.mask);
  107.  
  108.     Global.region.pix    = pix;
  109.     Global.region.mask   = mask;
  110.     Global.region.width  = width;
  111.     Global.region.height = height;
  112.  
  113.     XtVaGetValues(paint, XtNcolormap, &Global.region.cmap, NULL);
  114.  
  115.     selectionOwner = XtOwnSelection(paint, XA_PRIMARY, Global.currentTime,
  116.             selectionConvert, selectionLost, selectionDone);
  117. }
  118.  
  119. static void    stdPasteCB(Widget paint, XtPointer infoArg, Atom *selection, Atom *type,
  120.                 XtPointer value, unsigned long *len, int *format)
  121. {
  122.     selectInfo    *info = (selectInfo*)infoArg;
  123.     Display        *dpy = XtDisplay(paint);
  124.     XRectangle    rect;
  125.     Pixmap        pix;
  126.     Colormap    cmap;
  127.     Pixmap        newMask = None;
  128.     GC         gc;
  129.  
  130.     if (type != NULL) {
  131.         info->count--;
  132.         if (*type == XA_BITMAP) {
  133.             int    wth, hth, dth;
  134.             Pixmap    pix = *(Pixmap*)value;
  135.  
  136.             GetPixmapWHD(dpy, pix, &wth, &hth, &dth);
  137.             if (info->pixmap == None ||
  138.                 info->depth < dth) {
  139.                 info->pixmap = pix;
  140.                 info->width  = wth;
  141.                 info->height = hth;
  142.                 info->depth  = dth;
  143.             }
  144.         } else if (*type == XA_PIXMAP) {
  145.             int    wth, hth, dth;
  146.             Pixmap    pix = *(Pixmap*)value;
  147.  
  148.             GetPixmapWHD(dpy, pix, &wth, &hth, &dth);
  149.             if (info->pixmap == None ||
  150.                 info->depth < dth) {
  151.                 info->pixmap = pix;
  152.                 info->width  = wth;
  153.                 info->height = hth;
  154.                 info->depth  = dth;
  155.             }
  156.         }
  157.         /*
  158.         **  Are there more possible selections comming?
  159.         */
  160.         if (info->count != 0)
  161.             return;
  162.  
  163.         /*
  164.         **  Now that we have gotten all of the selections
  165.         **    use the best one.
  166.         */
  167.         if (info->pixmap != None) {
  168.             Pixmap    np;
  169.             GC    gc;
  170.  
  171.             if (Global.region.pix != None)
  172.                 XFreePixmap(dpy, Global.region.pix);
  173.             if (Global.region.mask != None)
  174.                 XFreePixmap(dpy, Global.region.mask);
  175.             if (Global.region.image != NULL)
  176.                 ImageDelete((Image*)Global.region.image);
  177.  
  178.             Global.region.pix   = None;
  179.             Global.region.mask  = None;
  180.             Global.region.image = NULL;
  181.  
  182.             np = XCreatePixmap(dpy, XtWindow(paint), 
  183.                     info->width, info->height, info->depth);
  184.             gc = XCreateGC(dpy, np, 0, 0);
  185.             XCopyArea(dpy, info->pixmap, np, gc, 
  186.                         0, 0, 
  187.                         info->width, info->height, 
  188.                         0, 0);
  189.  
  190.             XFreeGC(dpy, gc);
  191.  
  192.             Global.region.width  = info->width;
  193.             Global.region.height = info->height;
  194.             Global.region.pix    = np;
  195.  
  196.             if (info->depth == 1)
  197.                 Global.region.cmap = -1;
  198.             else
  199.                 Global.region.cmap = DefaultColormapOfScreen(XtScreen(paint));
  200.         }
  201.  
  202.         XtFree((XtPointer)info);
  203.     }
  204.  
  205.     /*
  206.     **  No valid selections anywhere or we own the selection.
  207.     */
  208.     if (Global.region.pix == None && Global.region.image == NULL)
  209.         return;
  210.     
  211.     rect.x = 0;
  212.     rect.y = 0;
  213.     rect.width = Global.region.width;
  214.     rect.height = Global.region.height;
  215.  
  216.     if (Global.region.mask != None) {
  217.         newMask = XCreatePixmap(dpy, XtWindow(paint), rect.width, rect.height, 1);
  218.         gc = XCreateGC(dpy, newMask, 0, 0);
  219.         XCopyArea(dpy, Global.region.mask, newMask, gc, 0, 0, rect.width, rect.height, 0, 0);
  220.         XFreeGC(dpy, gc);
  221.     } else if (Global.region.image != NULL && ((Image*)Global.region.image)->maskData != NULL) {
  222.         newMask = ImageMaskToPixmap(paint, (Image*)Global.region.image);
  223.     }
  224.  
  225.     XtVaGetValues(paint, XtNcolormap, &cmap, NULL);
  226.     if (cmap != Global.region.cmap) {
  227.         Image    *image;
  228.         Pixmap    npix = None;
  229.  
  230.         if (rect.width * rect.height > 1024)
  231.             StateSetBusy(True);
  232.  
  233.         if (Global.region.pix == None) {
  234.             image = (Image*)Global.region.image;
  235.             image->refCount++;
  236.         } else  {
  237.             image = PixmapToImage(paint, Global.region.pix, Global.region.cmap);
  238.         }
  239.  
  240.         ImageToPixmapCmap(image, paint, &npix, cmap);
  241.  
  242.         PwRegionSet(paint, &rect, npix, newMask);
  243.  
  244.         if (rect.width * rect.height > 1024)
  245.             StateSetBusy(False);
  246.     } else {
  247.         int    depth;
  248.  
  249.         XtVaGetValues(paint, XtNdepth, &depth, NULL);
  250.         pix = XCreatePixmap(dpy, XtWindow(paint), rect.width, rect.height, depth);
  251.         gc = XtGetGC(paint, 0, 0);
  252.         XCopyArea(dpy, Global.region.pix, pix, gc, 0, 0, rect.width, rect.height, 0, 0);
  253.         XtReleaseGC(paint, gc);
  254.  
  255.         PwRegionSet(paint, &rect, pix, newMask);
  256.     }
  257.  
  258.     setToSelectOp();
  259. }
  260. void StdPasteCallback(Widget w, XtPointer paintArg, XtPointer junk)
  261. {
  262.     Widget        paint = (Widget)paintArg;
  263.     int        flg = True;
  264.  
  265.     if (!selectionOwner) {
  266.         static Atom    targets[2] = { XA_PIXMAP, XA_BITMAP };
  267.         XtPointer    data[2];
  268.         selectInfo    *info = XtNew(selectInfo);
  269.  
  270.         info->count = XtNumber(targets);
  271.         info->pixmap = None;
  272.  
  273.         data[0] = (XtPointer)info;
  274.         data[1] = (XtPointer)info;
  275.  
  276.         XtGetSelectionValues(paint, XA_PRIMARY, targets, 2,
  277.                 stdPasteCB, data, Global.currentTime);
  278.     } else {
  279.         stdPasteCB(paint, NULL, NULL, NULL, 0, NULL, NULL);
  280.     }
  281. }
  282.  
  283. void StdClearCallback(Widget w, XtPointer paintArg, XtPointer junk2)
  284. {
  285.     Widget    paint = (Widget)paintArg;
  286.  
  287.     PwRegionClear(paint);
  288. }
  289.  
  290. void StdCutCallback(Widget w, XtPointer paintArg, String *nm, XEvent *event)
  291. {
  292.     StdCopyCallback(w, paintArg, nm, event);
  293.     StdClearCallback(w, paintArg, NULL);
  294. }
  295.  
  296. void StdDuplicateCallback(Widget w, XtPointer paintArg, XtPointer junk2)
  297. {
  298.     XRectangle    rect;
  299.     Widget        paint = (Widget)paintArg;
  300.     Pixmap        pix, mask;
  301.     int        width, height;
  302.  
  303.     if (!PwRegionGet(paint, &pix, &mask))
  304.         return;
  305.  
  306.     GetPixmapWHD(XtDisplay(paint), pix, &width, &height, NULL);
  307.  
  308.     rect.x = 0;
  309.     rect.y = 0;
  310.     rect.width = width;
  311.     rect.height = height;
  312.  
  313.     PwRegionSet(paint, &rect, pix, mask);
  314. }
  315.  
  316. void StdSelectAllCallback(Widget w, XtPointer paintArg, XtPointer junk2)
  317. {
  318.     Widget        paint = (Widget)paintArg;
  319.     XRectangle    rect;
  320.     int        dw, dh;
  321.  
  322.     XtVaGetValues(paint, XtNdrawWidth, &dw, XtNdrawHeight, &dh, NULL);
  323.  
  324.     rect.x = 0;
  325.     rect.y = 0;
  326.     rect.width  = dw;
  327.     rect.height = dh;
  328.  
  329.     PwRegionSet(paint, &rect, None, None);
  330.     setToSelectOp();
  331. }
  332. void StdUndoCallback(Widget w, XtPointer paintArg, XtPointer junk2)
  333. {
  334.     UndoSwap((Widget)paintArg);
  335. }
  336.  
  337. void ClipboardSetImage(Widget w, Image *image)
  338. {
  339.     if (Global.region.pix != None)
  340.         XFreePixmap(XtDisplay(w), Global.region.pix);
  341.     if (Global.region.mask != None)
  342.         XFreePixmap(XtDisplay(w), Global.region.mask);
  343.     if (Global.region.image != NULL)
  344.         ImageDelete(Global.region.image);
  345.  
  346.     Global.region.pix    = None;
  347.     Global.region.mask   = None;
  348.     Global.region.cmap   = None;
  349.     Global.region.image  = (void*)image;
  350.     Global.region.width  = image->width;
  351.     Global.region.height = image->height;
  352. }
  353.  
  354. /*
  355. **  End of "edit" menu function, start region menu functions.
  356. **
  357. */
  358.  
  359. void StdRegionFlipX(Widget w, XtPointer paintArg, XtPointer junk2)
  360. {
  361.     Widget    paint = (Widget)paintArg;
  362.     float    v = -1.0;
  363.  
  364.     PwRegionAddScale(paint, &v, NULL);
  365. }
  366.  
  367. void StdRegionFlipY(Widget w, XtPointer paintArg, XtPointer junk2)
  368. {
  369.     Widget    paint = (Widget)paintArg;
  370.     float    v = -1.0;
  371.  
  372.     PwRegionAddScale(paint, NULL, &v);
  373. }
  374.  
  375. /*
  376. **  
  377. */
  378. static void stdImgProcess(Widget paint, Image *(*func)(Image *))
  379. {
  380.     Pixmap        pix;
  381.     Colormap    cmap;
  382.     Image        *in, *out;
  383.  
  384.     StateSetBusy(True);
  385.  
  386.     if (!PwRegionGet(paint, &pix, None)) {
  387.         StateSetBusy(False);
  388.         return;
  389.     }
  390.  
  391.     PwRegionTear(paint);
  392.     XtVaGetValues(paint, XtNcolormap, &cmap, NULL);
  393.  
  394.     in = PixmapToImage(paint, pix, cmap);
  395.     out = func(in);
  396.     ImageDelete(in);
  397.     ImageToPixmapCmap(out, paint, &pix, cmap);
  398.  
  399.     PwRegionSetRawPixmap(paint, pix);
  400.  
  401.     StateSetBusy(False);
  402. }
  403.  
  404. void StdRegionInvert(Widget w, XtPointer paintArg, XtPointer junk2)
  405. {
  406.     Widget        paint = (Widget)paintArg;
  407.  
  408.     stdImgProcess(paint, ImageInvert);
  409. }
  410. void StdRegionSharpen(Widget w, XtPointer paintArg, XtPointer junk2)
  411. {
  412.     Widget        paint = (Widget)paintArg;
  413.  
  414.     stdImgProcess(paint, ImageSharpen);
  415. }
  416. void StdRegionSmooth(Widget w, XtPointer paintArg, XtPointer junk2)
  417. {
  418.     Widget        paint = (Widget)paintArg;
  419.  
  420.     stdImgProcess(paint, ImageSmooth);
  421. }
  422. void StdRegionEdge(Widget w, XtPointer paintArg, XtPointer junk2)
  423. {
  424.     Widget        paint = (Widget)paintArg;
  425.  
  426.     stdImgProcess(paint, ImageEdge);
  427. }
  428. void StdRegionEmbose(Widget w, XtPointer paintArg, XtPointer junk2)
  429. {
  430.     Widget        paint = (Widget)paintArg;
  431.  
  432.     stdImgProcess(paint, ImageEmbose);
  433. }
  434. void StdRegionOilPaint(Widget w, XtPointer paintArg, XtPointer junk2)
  435. {
  436.     Widget        paint = (Widget)paintArg;
  437.  
  438.     stdImgProcess(paint, ImageOilPaint);
  439. }
  440.  
  441. /*
  442. **  Start callback functions
  443. */
  444. static void prCallback(Widget paint, Widget w, Boolean flag)
  445. {
  446.     XtVaSetValues(w, XtNsensitive, flag, NULL);
  447. }
  448. static void addFunction(Widget item, Widget paint, XtCallbackProc func)
  449. {
  450.     XtAddCallback(item, XtNcallback, func, (XtPointer)paint);
  451.     XtAddCallback(paint, XtNregionCallback, (XtCallbackProc)prCallback, (XtPointer)item);
  452.     XtVaSetValues(item, XtNsensitive, (XtPointer)False, NULL);
  453. }
  454.  
  455. void ccpAddUndo(Widget w, Widget paint)
  456. {
  457.     XtAddCallback(w, XtNcallback, StdUndoCallback, (XtPointer)paint);
  458. }
  459. void ccpAddCut(Widget w, Widget paint)
  460. {
  461.     addFunction(w, paint, (XtCallbackProc)StdCutCallback);
  462. }
  463.  
  464. void ccpAddCopy(Widget w, Widget paint)
  465. {
  466.     addFunction(w, paint, (XtCallbackProc)StdCopyCallback);
  467. }
  468.  
  469. void ccpAddPaste(Widget w, Widget paint)
  470. {
  471.     XtVaSetValues(w, XtNsensitive, True, NULL);
  472.     XtAddCallback(w, XtNcallback, 
  473.         (XtCallbackProc)StdPasteCallback, (XtPointer)paint);
  474. }
  475. void ccpAddClear(Widget w, Widget paint)
  476. {
  477.     addFunction(w, paint, (XtCallbackProc)StdClearCallback);
  478. }
  479. void ccpAddDuplicate(Widget w, Widget paint)
  480. {
  481.     addFunction(w, paint, (XtCallbackProc)StdDuplicateCallback);
  482. }
  483.  
  484. /*
  485. **  Region functions
  486. */
  487. void ccpAddSaveRegion(Widget w, Widget paint)
  488. {
  489.     addFunction(w, paint, (XtCallbackProc)StdSaveRegionFile);
  490. }
  491. void ccpAddRegionFlipX(Widget w, Widget paint)
  492. {
  493.     addFunction(w, paint, (XtCallbackProc)StdRegionFlipX);
  494. }
  495. void ccpAddRegionFlipY(Widget w, Widget paint)
  496. {
  497.     addFunction(w, paint, (XtCallbackProc)StdRegionFlipY);
  498. }
  499. void ccpAddRegionInvert(Widget w, Widget paint)
  500. {
  501.     addFunction(w, paint, (XtCallbackProc)StdRegionInvert);
  502. }
  503. void ccpAddRegionSharpen(Widget w, Widget paint)
  504. {
  505.     addFunction(w, paint, (XtCallbackProc)StdRegionSharpen);
  506. }
  507. void ccpAddRegionSmooth(Widget w, Widget paint)
  508. {
  509.     addFunction(w, paint, (XtCallbackProc)StdRegionSmooth);
  510. }
  511. void ccpAddRegionEdge(Widget w, Widget paint)
  512. {
  513.     addFunction(w, paint, (XtCallbackProc)StdRegionEdge);
  514. }
  515. void ccpAddRegionEmbose(Widget w, Widget paint)
  516. {
  517.     addFunction(w, paint, (XtCallbackProc)StdRegionEmbose);
  518. }
  519. void ccpAddRegionOilPaint(Widget w, Widget paint)
  520. {
  521.     addFunction(w, paint, (XtCallbackProc)StdRegionOilPaint);
  522. }
  523.  
  524. /*
  525. **  Standard poup menu
  526. */
  527. static PaintMenuItem    popupMenu[] = {
  528.     MI_SEPERATOR(),
  529. #define P_UNDO_ITEM    1
  530.     MI_SIMPLE("undo"),
  531.     MI_SEPERATOR(),
  532. #define P_CUT_ITEM    3
  533.     MI_SIMPLE("cut"),
  534. #define P_COPY_ITEM    4
  535.     MI_SIMPLE("copy"),
  536. #define P_PASTE_ITEM    5
  537.     MI_SIMPLE("paste"),
  538. #define P_CLEAR_ITEM    6
  539.     MI_SIMPLE("clear"),
  540. };
  541.  
  542. void ccpAddStdPopup(Widget paint)
  543. {
  544.     MenuPopupCreate(XtParent(paint), XtNumber(popupMenu), popupMenu);
  545.  
  546.     ccpAddUndo(popupMenu[P_UNDO_ITEM].widget, paint);
  547.     ccpAddCut(popupMenu[P_CUT_ITEM].widget, paint);
  548.     ccpAddCopy(popupMenu[P_COPY_ITEM].widget, paint);
  549.     ccpAddPaste(popupMenu[P_PASTE_ITEM].widget, paint);
  550.     ccpAddClear(popupMenu[P_CLEAR_ITEM].widget, paint);
  551. }
  552.